// 该函数对parentwritePipe.c程序进行了修改。这里的修改说明了如何使用对管道的读操作进行同步。
// 其中，父进程在创建其n-1个子进程前就创建了管道。在创建了所有的子进程后，父进程向管道中写入n个字符。
// 包括父进程在内的每个子进程都会在向标准错误输出信息前，从管道中读取一个字符。
// 由于管道中的读操作会一直阻塞到有内容可读为止，因此每个子进程都会等待，直到父进程向管道写入为止，
// 这样就提供了一个被称为屏障(Barrier)的同步点

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "restart.h"

int synchronizefan(char *path) {
    char buf[] = "g";
    pid_t childpid = 0;
    int fd[2];
    int i, n, ret;

    // 设定子进程的数量
    n = atoi(path);

    // 创建同步的管道
    if (pipe(fd) == -1) {
        perror("Failed to create the synchronization pipe");
        return -1;
    }

    // 父进程创建n个子进程
    for (i = 1; i <= n; i++) {
        // 如果成功创建子进程，则break出for循环，因此为一个父进程创建了4个子进程，而不是链式进程
        if ((childpid = fork()) <= 0) {
            // fprintf(stderr, "the childpid %d create failed!\n", i);
            // perror("Failedd to create child fork");
            break;
        }
    }

    // 父进程将同步字符写入到管道中
    if (childpid) {
        for (i = 1; i <= n; i++) {
            ret = r_write(fd[1], buf, sizeof(buf));
            // 这是与1进行判断，是因为buf中的数组长度为1
            if (ret == 1) perror("Failed to write synchronization characters");
        }
    }

    // 子进程同步
    if (r_read(fd[0], buf, 1) != 1) {
        perror("Failed to read synchronization characters");
    }

    fprintf(stderr, "i: %d process ID: %ld, parent ID: %ld, child ID: %ld\n", i, (long)getpid(), (long)getppid(), (long)childpid);

    return (childpid == -1);

}

int main (int argc, char *argv[]) {
    // 检查有效的命令行参数个数
    if (argc != 2) {
        fprintf(stderr, "Usage: %s processes\n", argv[0]);
        return 1;
    }

    return synchronizefan(argv[1]);

    //return 0;
}